package com.sunday.common.mybatis.plus.core;

import com.baomidou.mybatisplus.core.metadata.TableFieldInfo;
import com.baomidou.mybatisplus.core.metadata.TableInfo;
import com.baomidou.mybatisplus.extension.toolkit.SqlHelper;
import com.sunday.common.core.lambda.ColumnMapperOperation;
import com.sunday.common.core.lambda.toolkit.support.ColumnMapper;
import com.sunday.common.core.lambda.toolkit.support.DefaultColumnMapper;
import com.sunday.common.core.lambda.toolkit.support.SFunction;

import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.stream.Collectors;

/**
 * mybatis plus 字段映射
 * 并且采用 mybatis plus 的 SqlHelper.table(target) 获取对应表结构信息
 * 便于优化初始化流程
 *
 * @author zsy
 * @since 2022/10/27
 */
public class MybatisPlusFieldMapping {

    private static final Map<String, Map<String, ColumnMapper>> COLUMN_CACHE_MAP = new ConcurrentHashMap<>();

    private static final ColumnMapperOperation OPERATION = new ColumnMapperOperation() {
        @Override
        public Map<String, ColumnMapper> getColumnMap(Class<?> target) {
            return COLUMN_CACHE_MAP.get(target.getName());
        }

        @Override
        public Map<String, ColumnMapper> createColumnMap(Class<?> target) {
            TableInfo tableInfo = SqlHelper.table(target);
            Map<String, ColumnMapper> map = tableInfo.getFieldList().stream()
                    .collect(Collectors.toMap(
                            TableFieldInfo::getProperty,
                            tableFieldInfo -> DefaultColumnMapper.of(tableFieldInfo.getProperty(), tableFieldInfo.getColumn())));
            map.put(tableInfo.getKeyProperty(),
                    DefaultColumnMapper.of(
                            tableInfo.getKeyProperty(),
                            tableInfo.getKeyColumn().isBlank() ? tableInfo.getKeyProperty() : tableInfo.getKeyColumn()));
            COLUMN_CACHE_MAP.put(target.getName(), map);
            return map;
        }
    };

    public static <T> String getColumnName(SFunction<T, ?> func) {
        return OPERATION.getColumnName(func);
    }

    public static String getColumnName(Class<?> target, String fieldName) {
        return OPERATION.getColumnName(target, fieldName);
    }

}
